package com.fantastic.web.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageInterceptor;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;

/**
 * @author: rxx
 * @since: 2024/5/24 07:50
 * @description: mybatisConfig配置类
 */
//标明为配置类
@Configuration
//扫描外部jdbc连接信息文件
@PropertySource("classpath:jdbc/jdbc.properties")
//开启自动事务代理
@EnableTransactionManagement
//扫描mapper层
@MapperScan("com.fantastic.mapper")
public class MybatisConfig {

    //读取properties文件的数据库连接信息，赋值到下面的字段。
    //使用@Value+${}  引用外部文件的值    （配合@PropertySource使用，指定外部文件资源）
    @Value("${jdbc.driverClassName}")
    private String driverClass;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 初始化数据源对象
     *
     * @return 返回一个数据源Bean对象交由springIOC容器进行管理
     * @Bean 往springIOC容器注册这个Bean
     */
    @Bean
    public DataSource dataSource() {
        //创建Druid数据源对象
        DruidDataSource dataSource = new DruidDataSource();
        //设置驱动
        dataSource.setDriverClassName(driverClass);
        //设置数据库url
        dataSource.setUrl(url);
        //设置用户名
        dataSource.setUsername(username);
        //设置密码
        dataSource.setPassword(password);
        //返回数据源对象
        return dataSource;
    }

    /**
     * 初始化mybatis的sql会话工程对象，交由spring管理。
     *
     * @param dataSource      数据源对象，    使用了@Autowired   spring容器会传递该值
     * @param pageInterceptor 分页拦截器对象
     * @return 返回sql会话工程对象
     */
    @Bean
    @Autowired
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource, PageInterceptor pageInterceptor) throws IOException {
        //创建会话对象
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //设置数据源对象
        sqlSessionFactoryBean.setDataSource(dataSource);
        //创建扫描对象
        PathMatchingResourcePatternResolver path = new PathMatchingResourcePatternResolver();
        //设置mapper.xml文件的位置。如果不打算使用xml映射sql语句，可以不设置。
        sqlSessionFactoryBean.setMapperLocations(path.getResources("classpath*:com/mapper/*.xml"));
        //设置分页拦截器
        sqlSessionFactoryBean.setPlugins(pageInterceptor);

        //返回
        return sqlSessionFactoryBean;
    }


    /**
     * 初始化分页拦截器
     *
     * @return
     */
    @Bean
    public PageInterceptor pageInterceptor() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        //设置数据库语言
        properties.setProperty("helperDialect", "mysql");
        //设置启用reasonable选项，
        // 这会使分页插件根据当前页码和页面大小自动调整分页参数。例如，如果请求的页码超出了总页数，插件会自动调整到最后一页。
        properties.setProperty("reasonable", "true");
        //如果设置为true 允许分页插件从方法参数中获取分页参数（如页码和页面大小）。
        properties.setProperty("supportMethodsArguments", "true");
        //设置为true时，会将RowBounds第一个参数offset当成pageNum页码使用
        properties.setProperty("offsetAsPageNum","true");
        //指定了一个参数映射count=countSql。这意味着在执行分页查询时，插件将使用countSql作为计算总记录数的SQL语句
        properties.setProperty("params", "count=countSql");
        //设置到分页拦截器中
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }


    /**
     * 配置平台事务管理器Bean
     *
     * @param dataSource @Autowired  自动注入dataSource
     * @return 返回平台事务管理器。此对象管理使用了@Transactional注解的类或是方法，开启事务
     */
    @Bean
    @Autowired
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager sourceTransactionManager = new DataSourceTransactionManager(dataSource);
        return sourceTransactionManager;
    }


}
